package com.gonsin.gmessage.logic.mqtt;

import com.gonsin.gmessage.logic.exceptions.GMessageException;
import com.gonsin.gmessage.logic.mqtt.config.MqttConfig;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.mqttv5.client.IMqttMessageListener;
import org.eclipse.paho.mqttv5.client.IMqttToken;
import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

//@Component
@Slf4j
public class MqttClientManager implements InitializingBean {

    @Autowired(required = false)
    private MqttConfig config;

    private MqttClient client;


    /**
     * 同一个topic如果重复监听，会导致前一个topic的监听无法收到，所以在该类中对topic进行管理
     */
    private Map<String, Set<IMqttMessageListener>> listenerMap;


    @Override
    public void afterPropertiesSet() throws Exception {
    }


    /**
     * 订阅topic
     * @param topic 订阅的topic字符串，格式例如  /venus/xxx/xxx
     * @param qos 监听质量  0/1/2
     * @param mqttMessageListener 监听的回调
     */
    public void subscribe(String topic, int qos, IMqttMessageListener mqttMessageListener){
        connectIfNot();
        Set<IMqttMessageListener> listeners = listenerMap.computeIfAbsent(topic, l -> {
            Set<IMqttMessageListener> ls = new HashSet<>();
            client.subscribe(topic, qos, (topic1, message) -> ls.forEach(ll -> {
                try {
                    ll.messageArrived(topic1, message);
                } catch (Exception e) {
                    log.error(e.toString(), e);
                }
            }));
            return ls;
        });
        listeners.add(mqttMessageListener);

    }


    /**
     * 发布topic
     * @param topic 发布的topic
     * @param qos 发布质量 0/1/2
     * @param payload 发布的内容
     */
    public IMqttToken publish(String topic, int qos, String payload){
        connectIfNot();
        return client.publish(topic, qos, payload);
    }

    private void connectIfNot(){
        if(client == null){
            listenerMap = new HashMap<>();
            if(config == null){
                log.error("你需要在代码里自行创建MqttConfig的Spring Bean对象");
                throw new GMessageException("需要配置MqttConfig");
            }

            client = new MqttClient(config);
            client.connect();
        }
    }
}
